/*
 * @Author: xmily
 * @Date: 2022-02-11 01:16:32
 * @LastEditors: xmily
 * @LastEditTime: 2023-09-11 00:24:15
 * @FilePath: \glxxapi\casbinAuth.js
 * @Description:
 * 用于权限认证的模块
 * Copyright (c) 2022 by xmily/mxthink.com.cn, All Rights Reserved.
 */

const sitecfg = require("./cfg/siteconfig.js");
const jwt = require("jsonwebtoken");

const { newEnforcer } = require("casbin");
const { MongooseAdapter } = require("casbin-mongoose-adapter");

exports.authorisation = function () {
  return async (ctx, next) => {
    //有token先解析token
    let role = "无角色";
    let token = ctx.header.authorization;
    console.log(token);
    if (ctx.header.authorization&&token!="undefined"&&token!="null") {
      try {
        //验证token合法性
        // if(ctx.header.authorization!="undefined"){
        let detoken = await jwt.verify(
          ctx.header.authorization,
          sitecfg.tokenKey
        );
      // }
        ctx.request.token = detoken;
      } catch (err) {
        console.log("all验证token时出错：[" + err + "]程序终止!请重新登录");
        ctx.body = {
          error: true,
          message: "验证token时出错，登录超时,请重新登录：[" + err + "]程序终止!",
        };
        return;
      }
      role = ctx.request.token.role;
    }

    var adapter = await MongooseAdapter.newAdapter(
      // "mongodb://glxx:19810921xMily@192.168.3.99:27017/glxx"
      "mongodb://127.0.0.1:27017/syxtest"
    );
    var e = await newEnforcer("./casbin_model.conf", adapter);
    ctx.state.enforcer = e;

    //#######不需权限可访问的目录##########
    let exceptionsDir = await e.getPermissionsForUser("exceptionsDir");

    for (index in exceptionsDir) {
      // eval("/^\"+item+"\/{0,1}$|^\"+item+"(\/.+)+/gm")
      // /^\/test\/{0,1}$|^\/test(\/.+)+/gm
      //正则匹配以下情况:/test|/test/|/test/abc|/test/abc/efg  不匹配以下情况：/abc/test/|/abc/test/efg。可以实现某目录下所有子目录均可匹配
      let reg = new RegExp(
        "^\\" +
          exceptionsDir[index][1] +
          "\\/{0,1}$|^\\" +
          exceptionsDir[index][1] +
          "(\\/.+)+",
        "gm"
      );
      if (reg.test(ctx.url)) {
        console.log(exceptionsDir[index][1] + "该目录下的路径不需要验证");
        await next();
        return;
      }
    }
    //#####################################
    //#######不需权限可访问的路径##########
    let exceptionsPath = await e.getPermissionsForUser("exceptionsPath");

    for (index in exceptionsPath) {
      // /^\/wechatforsvr\?.+|^\/wechatforsvr$/gm
      let reg = new RegExp(
        "^\\" +
          exceptionsPath[index][1] +
          "\\?.+|^\\" +
          exceptionsPath[index][1] +
          "$",
        "gm"
      );
      if (reg.test(ctx.url)) {
        console.log(ctx.url + "该路径不需要验证");
        await next();
        return;
      }
    }
    //#####################################

    //登录验证及权限验证开始
    if (!ctx.header.authorization) {
      console.log("token验证出错all");
      ctx.body = { error: true, message: "验证token时出错：程序终止!" };
      return;
    }
    let path = ctx.request.path; //获取当前请求路径
    let method = ctx.request.method; //获取当前请用的方法

    let authorised = await e.enforce(role, path, method);

    if (!authorised&&role!="管理员") {
      ctx.status = 403;
      console.log("无权限访问当前路径：" + path);
      return;
    }
    console.log("有权访问当前路径:" + path);
    await next();
  };
};
